#include "stdafx.h"
#include "gp_Ax2d.h"
#include "gp_Ax22d.h"
#include "gp_Pnt2d.h"
#include "gp_Trsf2d.h"
#include "gp_Vec2d.h"
#include "gp_Parab2d.h"
#include "gp.h"

gp_Parab2d::gp_Parab2d (const gp_Ax22d& D, 
	const gp_Pnt2d& F)
{
	gp_XY DCoord = D.XDirection().XY();
	gp_XY GCoord = D.YDirection().XY();
	gp_XY PCoord = D.Location().XY();
	gp_XY MCoord = F.XY();
	focalLength = DCoord.Dot ( MCoord.Subtracted (PCoord));
	if (focalLength < 0) focalLength = - focalLength;
	gp_XY N = GCoord;
	N.Multiply (focalLength);
	MCoord.Add (N);
	N.Reverse();
	pos = gp_Ax22d (gp_Pnt2d (MCoord), gp_Dir2d (N));
	focalLength = focalLength / 2.0;
}

gp_Parab2d::gp_Parab2d (const gp_Ax2d& D, 
	const gp_Pnt2d& F,
	const bool Sense)
{
	gp_XY DCoord = D.Direction().XY();
	gp_XY PCoord = D.Location().XY();
	gp_XY MCoord = F.XY();
	focalLength = DCoord.Dot ( MCoord.Subtracted (PCoord));
	if (focalLength < 0) focalLength = - focalLength;
	gp_XY N;
	if (Sense) N.SetCoord(DCoord.Y(), -DCoord.X());
	else  N.SetCoord(-DCoord.Y(), DCoord.X());
	N.Multiply (focalLength);
	MCoord.Add (N);
	N.Reverse();
	pos = gp_Ax22d (gp_Pnt2d (MCoord), gp_Dir2d (N),Sense);
	focalLength = focalLength / 2.0;
}

void gp_Parab2d::Coefficients
	(double& A, double& B, double& C,
	double& D, double& E, double& F) const
{
	double P = 2.0 * focalLength;
	gp_Trsf2d T;
	T.SetTransformation (pos.XAxis());
	double T11 = T.Value (1, 1);
	double T12 = T.Value (1, 2);
	double T13 = T.Value (1, 3);
	double T21 = T.Value (2, 1);
	double T22 = T.Value (2, 2);
	double T23 = T.Value (2, 3);
	A = T21 * T21;
	B = T22 * T22;
	C = T21 * T22;
	D = (T21 * T23) - (P * T11);
	E = (T22 * T23) - (P * T12);
	F = (T23 * T23) - (2.0 * P * T13);
}

void gp_Parab2d::Mirror (const gp_Pnt2d& P)
{ pos.Mirror (P); }

gp_Parab2d gp_Parab2d::Mirrored (const gp_Pnt2d& P) const
{
	gp_Parab2d Prb = *this;
	Prb.pos.Mirror (P);
	return Prb;     
}

void gp_Parab2d::Mirror (const gp_Ax2d& A)
{ pos.Mirror (A); }

gp_Parab2d gp_Parab2d::Mirrored (const gp_Ax2d& A) const
{
	gp_Parab2d Prb = *this;
	Prb.pos.Mirror (A);
	return Prb;     
}

 gp_Parab2d::gp_Parab2d () :
focalLength(DBL_MAX)
{ }

 gp_Parab2d::gp_Parab2d (const gp_Ax22d& A, 
			       const double Focal) :
			       pos (A), 
			       focalLength (Focal) 
{ Standard_ConstructionError_Raise_if(Focal < 0.0,""); }

 gp_Parab2d::gp_Parab2d (const gp_Ax2d& MirrorAxis, 
			       const double Focal,
			       const bool Sense) :
			       focalLength (Focal) 
{
  pos = gp_Ax22d(MirrorAxis,Sense);
  Standard_ConstructionError_Raise_if(Focal < 0.0,"");
}

 void gp_Parab2d::SetFocal (const double Focal)
{ 
  Standard_ConstructionError_Raise_if(Focal < 0.0,"");
  focalLength = Focal;
}

 void gp_Parab2d::SetLocation   (const gp_Pnt2d& P)
{ pos.SetLocation(P); }

 void gp_Parab2d::SetMirrorAxis (const gp_Ax2d& A)
{ pos.SetXAxis(A); }

 void gp_Parab2d::SetAxis (const gp_Ax22d& A)
{ pos.SetAxis(A); }

 gp_Ax2d gp_Parab2d::Directrix() const
{
  gp_Pnt2d P (pos.Location().X() - focalLength * pos.XDirection().X(),
	      pos.Location().Y() - focalLength * pos.XDirection().Y() );
  gp_Dir2d V (pos.YDirection().Reversed());
  return gp_Ax2d (P, V);
}

   double gp_Parab2d::Focal() const
{ return focalLength; }

 gp_Pnt2d gp_Parab2d::Focus() const
{
  return gp_Pnt2d (pos.Location().X() + focalLength * pos.XDirection().X(),
		   pos.Location().Y() + focalLength * pos.XDirection().Y());
}

 gp_Pnt2d gp_Parab2d::Location () const
{ return pos.Location(); }

 gp_Ax2d gp_Parab2d::MirrorAxis () const 
{ return pos.XAxis(); }

 gp_Ax22d gp_Parab2d::Axis () const 
{ return pos; }

 double gp_Parab2d::Parameter()  const
{ return 2.0 * focalLength; }

 void gp_Parab2d::Reverse() 
{
  gp_Dir2d Temp = pos.YDirection ();
  Temp.Reverse ();
  pos.SetAxis(gp_Ax22d(pos.Location(),pos.XDirection(),Temp));
}

 gp_Parab2d gp_Parab2d::Reversed() const
{
  gp_Parab2d P = *this;
  gp_Dir2d Temp = pos.YDirection ();
  Temp.Reverse ();
  P.pos.SetAxis(gp_Ax22d(pos.Location(),pos.XDirection(),Temp));
  return P;
}

 bool gp_Parab2d::IsDirect() const
{ return (pos.XDirection().Crossed(pos.YDirection())) >= 0.0; }

 void gp_Parab2d::Rotate (const gp_Pnt2d& P,
				const double Ang)
{pos.Rotate (P, Ang);}

 gp_Parab2d gp_Parab2d::Rotated (const gp_Pnt2d& P,
				       const double Ang) const
{
  gp_Parab2d Prb = *this;
  Prb.pos.Rotate (P, Ang);
  return Prb;     
}

 void gp_Parab2d::Scale (const gp_Pnt2d& P,
			       const double S)
{
  focalLength *= S;
  if (focalLength < 0) focalLength = - focalLength;
  pos.Scale (P, S);
}

 gp_Parab2d gp_Parab2d::Scaled (const gp_Pnt2d& P,
				      const double S) const
{
  gp_Parab2d Prb = *this;
  Prb.focalLength *= S;
  if (Prb.focalLength < 0) Prb.focalLength = - Prb.focalLength;
  Prb.pos.Scale (P, S);
  return Prb;     
}

 void gp_Parab2d::Transform (const gp_Trsf2d& T)
{ 
  focalLength *= T.ScaleFactor();
  if (focalLength < 0) focalLength = - focalLength;
  pos.Transform (T); 
}

 gp_Parab2d gp_Parab2d::Transformed (const gp_Trsf2d& T) const
{
  gp_Parab2d Prb = *this;
  Prb.focalLength *= T.ScaleFactor();
  if (Prb.focalLength < 0) Prb.focalLength = - Prb.focalLength;
  Prb.pos.Transform (T);
  return Prb;     
}

 void gp_Parab2d::Translate (const gp_Vec2d& V)
{ pos.Translate (V); }

 gp_Parab2d gp_Parab2d::Translated (const gp_Vec2d& V) const
{
  gp_Parab2d Prb = *this;
  Prb.pos.Translate(V);
  return Prb;     
}

 void gp_Parab2d::Translate (const gp_Pnt2d& P1,
				   const gp_Pnt2d& P2)
{ pos.Translate (P1, P2); }

 gp_Parab2d gp_Parab2d::Translated (const gp_Pnt2d& P1,
					  const gp_Pnt2d& P2) const
{
  gp_Parab2d Prb = *this;
  Prb.pos.Translate (P1, P2);
  return Prb;     
}

